# -*- coding: utf-8 -*-
'''
Module name: SrcReader

Created on 2013-3-13

@author: yangyil
'''
import mmap

class SrcReader:
    '''
    Supply the functions to read the source file
    '''


    def __init__(self, filepath):
        '''
        Load the source file.
        '''
        with open(filepath, "r+b") as srcfile:
            self._map = mmap.mmap(srcfile.fileno(), 0)
    
    def Read(self,size = 1):
        '''
        Read from the source file by size.
        '''
        return self._map.read(size)
    
    def ReadBLOB(self,size):
        '''
        Read a BLOB variable from the source file, strip the quotation marks and check the validity.
        '''
        check = self._map.read(1)
        if check != '\"':
            raise ValueError,"ERROR: unexpected char , should be '\"'."
        buffRet = self._map.read(size)
        check = self._map.read(1)
        if check != '\"':
            raise ValueError,"ERROR: unexpected char , should be '\"'"
        check = self._map.read(1)
        if check == '\r':
            check = self._map.read(1)
        if check != ',' and check != '\n' and check != '':
            raise ValueError,"ERROR: unexpected char , should be ',' or '\n' or none."
        return buffRet
        
    def ReadBy(self,delimiter):
        '''
        Read from the source file until the assigned delimiter.
        '''
        iFind = self._map.find(delimiter)
        if iFind != -1:
            size = iFind - self._map.tell()
            buffRet = self._map.read(size)
            check = self._map.read(1)
            if check != ',' and check != '\n':
                raise "ERROR: unexpected char , should be ',' or '\n'"
            return buffRet
        else:
            return -1
    
    def GetCursor(self):
        '''
        Get the current cursor of the source file.
        '''
        return self._map.tell()
    
    def SetCursor(self,cursor):
        '''
        Set the cursor of the source file to the assigned.
        '''
        self._map.seek(cursor)
    
    def getN(self, size = 1, reverse = True):
        '''
        Get 'N'-kind variable from the source file.
        '''
        return self.getBinNumber(self.Read(size)[::-1])
    
    def getSWS(self, reverse = True):
        '''
        Get 'SWS'-kind variable from the source file.
        '''
        temp = self.getBinNumber(self.Read(2)[::-1])
        return 2*temp
#        if temp == 16**4 - 1:
#            return temp
#        else:
#            return 2*temp
        
    def isEnd(self):
        '''
        Tell if the cursor meets the end of the source file.
        '''
        return self._map.tell() == self._map.size()
    
    @staticmethod
    def getBinNumber(strBuff):
        '''
        Calculate the strBuff as binary.
        '''
        temp = [ord(m) for m in strBuff]
        return reduce(lambda x,y: (x<<8) + y, temp)